package com.mapbased.wfw;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

import org.dom4j.Element;

/**
 *
 * <p>Title: </p>
 *
 * <p>Description: Every page have a PageHandler</p>
 *
 * <p>Copyright: Copyright (c) 2004</p>
 *
 * <p>Company: </p>
 *
 * @author chy(Baily)
 * @version 1.0
 */
public abstract class PageHandler
{

     long lastVisitTime;

    //   private String locale=null;
    protected Properties resStrings=null;
    protected String pagePath;
    Validating[] validators;
    /**
     *
     * @param context RenderContext
     * @return Object:String value to the page to redirect, if is null,this page
     */
    public Object defaultAction(RenderContext context)
    {
        return null;
    }

    protected void beforeRender(RenderContext rc)
    {}

    final private static Class[] ACTION_METHOD_PARAS=new Class[]
        {
        RenderContext.class};

    ////////////////////////////////////////////////////////////////////////
//    /**
//     *  dynamic enerate code using javassist
//     * @param rc RenderContext
//
//     */
//    private boolean hasGeneated=false;
//    /**
//     * do not overwrite this  method ,auto done by javassist
//     * @param rc RenderContext
//     * @return Object
//     */
//    final protected Object geneated(RenderContext rc)
//    {
//        return null;
//    }
//
//    private void geneate(String action)
//    {
//        String name=this.getClass().getName();
//        System.out.println(name);
//        try
//        {
//
//            CtClass clz=javassist.ClassPool.getDefault().get(name);
//            CtMethod md=clz.getDeclaredMethod("geneated");
//            String body="return " + action + "Action($1);";
//            md.setBody(body);
//
//        }
//        catch(Exception ex)
//        {
//            throw new java.lang.RuntimeException(ex);
//        }
//        this.hasGeneated=true;
//
//    }

    ///////////////////////////////////////////////////////////
    protected Object refactionDispatch(String actionName,RenderContext context)
    {
        try
        {
            Method m=this.getClass().getMethod(
                actionName.concat("Action"),ACTION_METHOD_PARAS);
            return m.invoke(this,new Object[]
                            {context});
        }
        catch(InvocationTargetException ex)
        {
            Throwable t=ex.getCause();

            while(t.getCause() != null)
            {
                t=t.getCause();
            }
            if(t instanceof RuntimeException)
            {
                throw(RuntimeException)t;
            }
            throw new java.lang.RuntimeException(ex);
        }

        catch(IllegalAccessException ex)
        {
            throw new java.lang.RuntimeException(ex);
        }

        catch(NoSuchMethodException ex)
        {
            throw new java.lang.RuntimeException(ex);
        }

    }

    /**
     *
     * @param context RenderContext
     */
    public Object dispatchAction(RenderContext context)
    {

        String actionMethod=context.getSureSingleParam(Constants.Page_Action);
        if(actionMethod.equals(""))
        {
            return this.defaultAction(context);
        }
        else
        {
            return this.refactionDispatch(actionMethod,context);
        }
//            if(this.hasGeneated)
//            {
//                return this.geneated(context);
//            }
//            else
//            {
//                this.geneate(actionMethod);
//            }
        //////////////////////////////

    }

    /**
     * get a resource string.
     * @param key String
     * @return String
     */
    final public String getString(String key)
    {
        return this.resStrings.getProperty(key);
    }

    protected void setLocale(String locale)
        throws IOException
    {
        //    this.locale=locale;
        this.resStrings=Util.loadRes(this.getClass(),locale);
    }

    /**
     * if  the handler want to know the pagepath,overload this method
     * @param s String
     */

    protected void setPagePath(String s)
    {
        this.pagePath=s;
    }

    /**
     * trigged when a file post to this page.give out a output stream to receive
     * the content.
     * @param context RenderContext
     * @param fieldName String
     * @param headers Map
     * @return OutputStream
     */

    protected java.io.OutputStream onDataUpload(RenderContext context,
                                                String fieldName,
                                                java.util.Map headers)
    {
        return null;
    }

    /**
     * fetch useful Attribute from the handler Element
     * use this to init some attributes for page handler
     * typicaly ,get some configure information
     * @param ele Element
     */
    protected void fetchAttributs(Element ele)
    {

    }

    protected void init(GlobalRef global)
    {

    }

    /**
     * for webservice call,return before renderer page
     * @param rc RenderContext
     * @param o Serializable
     * @return ExitException
     */

    protected ExitException serviceReturn(RenderContext rc,
                                          com.mapbased.wfw.ws.WSResult o)
    {
        ObjectOutputStream oos=null;
        try
        {
            oos=new java.io.ObjectOutputStream(
                rc.getResponse().getOutputStream());
            oos.writeObject(o);
        }
        catch(IOException ex)
        {
            throw new java.lang.RuntimeException(ex);
        }
        finally
        {
            if(oos != null)
            {
                try
                {
                    oos.close();
                }
                catch(IOException ex1)
                {
                }
            }
        }
        return ExitException.INSTANCE;

    }

    protected void doValidate(RenderContext rc)
    {
        for(int i=0;i < this.validators.length;i++)
        {
            this.validators[i].validate(rc);

        }
    }

    public String getPagePath()
    {
        return pagePath;
    }

    public long getLastVisitTime()
    {
        return lastVisitTime;
    }

    public String pagePathBinding(RenderContext ctx)
    {
        return pagePath; //ctx.getPageHandler().getPagePath();
    }

    public Object servletContextBinding(RenderContext rc)
    {
        rc.global.getServletContext().getServletContextName().endsWith("main");
        return rc.global.getServletContext(); //.getServletContextName();
    }

    public String clientLocaleBinding(RenderContext rc)
    {
        return rc.getLocale();
    }

    final protected int getPageConfigInt(GlobalRef g,String name,int v)
    {
        String s=getPageConfig(g,name,"" + v);
        if(s == null || s.length() == 0)
        {
            return v;
        }

        return Integer.parseInt(s);

    }

    final protected int getPageConfigInt(GlobalRef g,String name)
    {
        String s=getPageConfig(g,name,"0");
        if(s == null || s.length() == 0)
        {
            return 0;
        }

        return Integer.parseInt(s);

    }

    final protected String getPageConfig(GlobalRef g,String name)
    {
        return getPageConfig(g,name,null);
    }

    final public String getPageConfig(GlobalRef g,String name,
                                      String defaultValue)
    {
        String basedir="mapbased-config/"
            + g.getServletContext().getServletContextName();
        File f=new File(basedir,this.pagePath);
        if(!f.exists())
        {
            f.mkdirs();

        }
        f=new File(f,name + ".txt");
        java.io.InputStream fi=null;
        try
        {
            if(f.exists())
            {
                fi=new java.io.BufferedInputStream(new java.io.FileInputStream(
                    f));

                java.io.ByteArrayOutputStream bos=new java.io.
                    ByteArrayOutputStream((int)f.length());

                int i=fi.read();
                while(i >= 0)
                {
                    bos.write(i);
                    i=fi.read();
                }
                fi.close();
                fi=null;

                return new String(bos.toByteArray(),"UTF-8");

            }
            else if(defaultValue != null)
            {
                java.io.FileOutputStream fos=new java.io.FileOutputStream(f);
                fos.write(defaultValue.getBytes("UTF-8"));
                fos.close();
                return defaultValue;
            }
            else
            {
                f.createNewFile();
                return null;
            }
        }
        catch(FileNotFoundException ex)
        {
            ex.printStackTrace();
            return defaultValue;
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
            return defaultValue;
        }
        finally
        {
            if(fi != null)
            {
                try
                {
                    fi.close();
                }
                catch(Exception ee)
                {
                    ee.printStackTrace();
                }
            }

        }

    }

}
